<template>
  <div class="container">
    <!-- 左侧组件面板 -->
    <div class="panel left-panel">
      <div
        v-for="component in componentList"
        :key="component.type"
        class="component-item"
        draggable="true"
        @dragstart="handleDragStart($event, component)"
      >
        {{ component.label }}
      </div>
    </div>

    <!-- 中间画布 -->
    <div class="panel canvas-panel" @dragover.prevent @drop="handleDrop">
      <div
        v-for="(item, index) in formComponents"
        :key="item.id"
        class="canvas-component"
        :class="{ active: selectedComponent?.id === item.id }"
        @click="selectComponent(item)"
      >
        <component
          :is="getComponent(item.type).component"
          v-model="formData[item.config.field]"
          v-bind="getComponentProps(item)"
        >
          <template v-if="item.type === 'select'">
            <el-option
              v-for="opt in parseOptions(item.config.options)"
              :key="opt.value"
              :label="opt.label"
              :value="opt.value"
            />
          </template>
        </component>
        <div class="component-actions">
          <button @click.stop="moveComponent(index, index - 1)">↑</button>
          <button @click.stop="moveComponent(index, index + 1)">↓</button>
          <button @click.stop="deleteComponent(index)">×</button>
        </div>
      </div>
    </div>

    <!-- 右侧属性面板 -->
    <div class="panel right-panel">
      <div v-if="selectedComponent" class="property-form">
        <h3>{{ selectedComponent.label }} 属性</h3>

        <div class="form-item">
          <label>字段名称：</label>
          <input
            v-model="selectedComponent.config.field"
            type="text"
            @change="handleFieldChange"
          />
        </div>

        <!-- 公共属性 -->
        <div class="form-item">
          <label>显示标签：</label>
          <input v-model="selectedComponent.config.label" type="text" />
        </div>

        <!-- 类型特定配置 -->
        <template v-if="selectedComponent.type === 'select'">
          <div class="form-item">
            <label>选项配置：</label>
            <textarea
              v-model="selectedComponent.config.options"
              placeholder="格式: value1:label1,value2:label2"
            ></textarea>
          </div>
        </template>

        <template v-if="selectedComponent.type === 'date'">
          <div class="form-item">
            <label>日期格式：</label>
            <select v-model="selectedComponent.config.format">
              <option value="YYYY-MM-DD">YYYY-MM-DD</option>
              <option value="YYYY/MM/DD">YYYY/MM/DD</option>
            </select>
          </div>
        </template>

        <template v-if="selectedComponent.type === 'switch'">
          <div class="form-item">
            <label>开启文字：</label>
            <input v-model="selectedComponent.config.activeText" type="text" />
          </div>
          <div class="form-item">
            <label>关闭文字：</label>
            <input
              v-model="selectedComponent.config.inactiveText"
              type="text"
            />
          </div>
        </template>

        <template v-if="selectedComponent.type === 'rate'">
          <div class="form-item">
            <label>最大评分：</label>
            <input
              v-model.number="selectedComponent.config.max"
              type="number"
              min="1"
              max="10"
            />
          </div>
          <div class="form-item">
            <label>
              <input
                v-model="selectedComponent.config.allowHalf"
                type="checkbox"
              />
              允许半选
            </label>
          </div>
        </template>
      </div>
    </div>

    <button class="save-btn" @click="saveForm">保存配置</button>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, h } from "vue";
import {
  ElInput,
  ElSelect,
  ElOption,
  ElDatePicker,
  ElSwitch,
  ElRate,
} from "element-plus";

type ComponentType =
  | "input"
  | "select"
  | "textarea"
  | "date"
  | "switch"
  | "rate";

interface FormComponent {
  id: string;
  type: ComponentType;
  label: string;
  config: {
    field: string;
    label: string;
    [key: string]: any;
  };
}

// 响应式数据
const formData = reactive<Record<string, any>>({});
const formComponents = reactive<FormComponent[]>([]);
const selectedComponent = ref<FormComponent | null>(null);

// 组件配置映射
const componentMap = {
  input: {
    component: ElInput,
    props: (config: any) => ({
      placeholder: config.placeholder,
      clearable: true,
    }),
  },
  select: {
    component: ElSelect,
    props: (config: any) => ({
      placeholder: config.placeholder,
      clearable: true,
    }),
  },
  textarea: {
    component: ElInput,
    props: (config: any) => ({
      type: "textarea",
      rows: 4,
      placeholder: config.placeholder,
    }),
  },
  date: {
    component: ElDatePicker,
    props: (config: any) => ({
      type: "date",
      format: config.format,
      placeholder: config.placeholder,
    }),
  },
  switch: {
    component: ElSwitch,
    props: (config: any) => ({
      activeText: config.activeText,
      inactiveText: config.inactiveText,
    }),
  },
  rate: {
    component: ElRate,
    props: (config: any) => ({
      max: config.max || 5,
      allowHalf: config.allowHalf,
    }),
  },
};

// 可用组件列表
const componentList = [
  { type: "input", label: "文本输入" },
  { type: "select", label: "下拉选择" },
  { type: "textarea", label: "多行文本" },
  { type: "date", label: "日期选择" },
  { type: "switch", label: "开关切换" },
  { type: "rate", label: "评分组件" },
];

// 工具方法
const generateId = () => Math.random().toString(36).slice(2, 11);

const parseOptions = (options: string) => {
  return (
    options?.split(",").map((opt) => {
      const [value, label] = opt.split(":");
      return {
        value: (value || "").trim(),
        label: (label || value || "").trim(),
      };
    }) || []
  );
};

// 拖拽处理
const handleDragStart = (e: DragEvent, component: any) => {
  e.dataTransfer?.setData("text/plain", JSON.stringify(component));
};

const handleDrop = (e: DragEvent) => {
  const componentData = JSON.parse(
    e.dataTransfer?.getData("text/plain") || "{}"
  );
  if (componentData.type) {
    const fieldName = `field_${Date.now()}`;
    const baseConfig = {
      field: fieldName,
      label: componentData.label,
      placeholder: "请输入内容",
    };

    const typeConfigs: Record<string, any> = {
      select: { options: "" },
      date: { format: "YYYY-MM-DD" },
      switch: {
        activeText: "开启",
        inactiveText: "关闭",
      },
      rate: { max: 5, allowHalf: false },
    };

    const newComponent: FormComponent = {
      id: generateId(),
      type: componentData.type,
      label: componentData.label,
      config: {
        ...baseConfig,
        ...(typeConfigs[componentData.type] || {}),
      },
    };

    formComponents.push(newComponent);
    formData[fieldName] = componentData.type === "switch" ? false : "";
  }
};

// 组件操作
const selectComponent = (component: FormComponent) => {
  selectedComponent.value = component;
};

const deleteComponent = (index: number) => {
  const [deleted] = formComponents.splice(index, 1);
  if (selectedComponent.value?.id === deleted.id) {
    selectedComponent.value = null;
  }
  delete formData[deleted.config.field];
};

const moveComponent = (oldIndex: number, newIndex: number) => {
  if (newIndex >= 0 && newIndex < formComponents.length) {
    const [component] = formComponents.splice(oldIndex, 1);
    formComponents.splice(newIndex, 0, component);
  }
};

// 字段重命名处理
const handleFieldChange = (e: Event) => {
  const input = e.target as HTMLInputElement;
  const oldField = input.dataset.oldValue;
  const newField = input.value;

  if (oldField && newField && oldField !== newField) {
    formData[newField] = formData[oldField];
    delete formData[oldField];
  }
};

// 保存配置
const saveForm = () => {
  const output = {
    schema: formComponents.map((comp) => ({
      type: comp.type,
      config: comp.config,
    })),
    data: { ...formData },
  };
  console.log("完整配置:", JSON.stringify(output, null, 2));
  alert("配置已保存到控制台");
};

// 辅助函数
const getComponent = (type: ComponentType) => componentMap[type];
const getComponentProps = (item: FormComponent) =>
  componentMap[item.type].props(item.config);
</script>

<style scoped>
.container {
  display: flex;
  height: 100vh;
  padding: 20px;
  gap: 20px;
  background: #f5f7fa;
}

.panel {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.left-panel {
  width: 240px;
  padding: 15px;
}

.canvas-panel {
  flex: 1;
  padding: 20px;
  min-height: 80vh;
  border: 2px dashed #e4e7ed;
}

.right-panel {
  width: 300px;
  padding: 20px;
}

.component-item {
  padding: 12px;
  margin: 8px 0;
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  cursor: move;
  transition: all 0.2s;
}

.component-item:hover {
  transform: translateX(4px);
  background: #e9ecef;
}

.canvas-component {
  position: relative;
  margin: 16px 0;
  padding: 20px;
  background: #fff;
  border: 2px solid transparent;
  border-radius: 6px;
  transition: all 0.3s;
}

.canvas-component.active {
  border-color: #2196f3;
  box-shadow: 0 4px 12px rgba(33, 150, 243, 0.15);
}

.component-actions {
  position: absolute;
  top: -12px;
  right: 10px;
  display: flex;
  gap: 6px;
  padding: 4px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.component-actions button {
  padding: 4px 8px;
  background: #2196f3;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  transition: opacity 0.2s;
}

.component-actions button:hover {
  opacity: 0.85;
}

.form-item {
  margin: 16px 0;
}

.form-item label {
  display: block;
  margin-bottom: 8px;
  color: #616161;
  font-weight: 500;
}

.form-item input,
.form-item select,
.form-item textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #bdbdbd;
  border-radius: 4px;
}

.save-btn {
  position: fixed;
  bottom: 20px;
  right: 20px;
  padding: 12px 24px;
  background: #2196f3;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}

.save-btn:hover {
  background: #1976d2;
}
</style>
